package io.github.ali.commons.variable;

import io.github.ali.commons.function.NAFunction;
import io.github.ali.commons.log.holder.CommonLoggerHolder;
import io.reactivex.BackpressureStrategy;

/**
 * 动作执行器
 * 
 * @author fuli
 * @date 2018年12月5日
 * @version 1.0.0
 */
public abstract class ActionExecuter implements CommonLoggerHolder{
	private static final String STATUS_INIT = "I";
	private static final String STATUS_RUNNING = "R";
	private static final String STATUS_STOP = "S";
	protected String name;
	private String status;
	private NAFunction action;
	private ActionHandler actionHandler;
	private long triggerTimes = 0;

	public ActionExecuter(NAFunction action) {
		name = this.toString();
		status = STATUS_INIT;
		this.action = action;
	}
	/**
	 * 触发执行动作,但不一定会执行
	 */
	protected void triggerExecute() {
		triggerTimes++;
		actionHandler.execute(action);
	}
	/**
	 * 默认LATEST
	 */
	public void start(){
		start(BackpressureStrategy.LATEST);
	}
	public synchronized void start(BackpressureStrategy backpressureStrategy){
		if (status == STATUS_INIT) {
			status = STATUS_RUNNING;
			actionHandler = ActionHandler.makeActionHandler(backpressureStrategy);
			actionHandler.init();
			postStart();
			LOGGER.info("the {}.{} has started !",this.getClass().getSimpleName(),name);
		}
	}
	public synchronized void stop(){
		if (status == STATUS_RUNNING) {
			preStop();
			actionHandler.destory();
			status = STATUS_STOP;
			LOGGER.info("the {}.{} has stopped !",this.getClass().getSimpleName(),name);
		}
	}
	public synchronized boolean restart() {
		if (status == STATUS_STOP) {
			status = STATUS_INIT;
			start();
			return true;
		}
		return false;
	}
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	/**
	 * 执行Action的总次数
	 * 
	 * @return
	 */
	public long getExecuteTimes() {
		return actionHandler.getExecuteTimes();
	}
	public boolean isRunning() {
		return status == STATUS_RUNNING;
	}
	/**
	 * 触发总次数
	 * @return
	 */
	public long getTriggerTimes(){
		return triggerTimes;
	}
	
	abstract protected void postStart();
	abstract protected void preStop();
}
